﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;

using iPhoneUI;
using iPhoneUI.Shell;
using iPhoneUI.Widgets;

namespace iPhoneUI
{
    public partial class WidgetHostForm : Form, IWidgetOwner
    {
        private Bitmap m_buffer;

        private ShellConfig m_shellConfig;
        private PageFactory m_pageFactory;

        private Page m_currentPage;

        private IDictionary<string, Page> m_pageMap = new Dictionary<string, Page>();
        private IDictionary<string, Widget> m_hostWidgets = new Dictionary<string, Widget>();

        private WidgetHostForm()
        {
        }

        public WidgetHostForm(ShellConfig shellConfig)
        {
            Debug.Assert(shellConfig != null);

            InitializeComponent();

            m_shellConfig = shellConfig;
            m_shellConfig.SetConfiguration(Width, Height);

            m_pageFactory = new PageFactory(this);

            m_buffer = new Bitmap(Width, Height, PixelFormat.Format32bppRgb);

            foreach (WidgetConfig config in m_shellConfig.HostConfig.Widgets)
            {
                Widget w = WidgetFactory.CreateWidget(this, config);
                WidgetFactory.PlaceWidget(ClientRectangle, m_hostWidgets.Values, w);
                m_hostWidgets.Add(config.Name, w);
            }            
            timer1.Interval = m_shellConfig.HostConfig.TimeOut;
        }

        public void GotoPage(string name)
        {
            if (name == "Exit")
            {
                if (ConfirmExit())
                    Close();

                return;
            }

            if (m_currentPage != null)
            {
                m_currentPage.Navigate -= new NavigationEventHandler(m_currentPage_Navigate);
                m_currentPage.Suspend();
            }

            if (m_pageMap.ContainsKey(name) == false)
                m_pageMap.Add(name, m_pageFactory.CreatePage(m_shellConfig.GetPage(name), PageBounds));

            m_currentPage = m_pageMap[name];
            m_currentPage.Navigate += new NavigationEventHandler(m_currentPage_Navigate);

            foreach (WidgetRefConfig widgetRef in m_currentPage.WidgetRefs)
                m_hostWidgets[widgetRef.Name].SetProperties(widgetRef.Properties);

            timer1.Enabled = m_currentPage.Name != "Home";

            m_currentPage.Resume();

            Invalidate();
        }

        public Size ScaleSize(Size size)
        {
            return ShellConfig.ScaleSize(size);
        }

        public int ScaleX(int x)
        {
            return ShellConfig.ScaleX(x);
        }

        public int ScaleY(int y)
        {
            return ShellConfig.ScaleY(y);
        }

        private void m_currentPage_Navigate(object sender, NavigationEventArgs args)
        {
            GotoPage(args.Target);
        }

        private static bool ConfirmExit()
        {
            return MessageBox.Show("Do really want to exit?", "Exit iPhone UI?", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes;
        }

        private void Navigate(object sender, NavigationEventArgs args)
        {
            if (string.IsNullOrEmpty(args.Target) == false)
                GotoPage(args.Target);
        }

        public Rectangle PageBounds
        {
            get
            {
                // this assumes that all host page widgets are snapped to the top
                int y = m_hostWidgets.Values.Max(w => w.ClientArea.Bottom);
                return new Rectangle(0, y, ClientRectangle.Width, Height - y);
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            ResetTimeoutTimer();
            
            m_currentPage.OwnerMouseDown(e.X, e.Y);

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            ResetTimeoutTimer();

            m_currentPage.OwnerMouseUp(e.X, e.Y);

            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            ResetTimeoutTimer();

            m_currentPage.OwnerMouseMove(e.X, e.Y);

            base.OnMouseMove(e);
        }

        public void Update(Rectangle rectangle)
        {
            Invalidate(rectangle);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            using (Graphics graphics = Graphics.FromImage(m_buffer))
            {
                graphics.Clear(Color.Black);

                m_currentPage.Draw(graphics, e.ClipRectangle);
 
                // draw widgets hosted directly on the form
                Canvas canvas = new Canvas(graphics);
                foreach(Widget w in m_hostWidgets.Values)
                    w.Draw(canvas, e.ClipRectangle);
            }

            e.Graphics.DrawImage(m_buffer, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }

        protected override void OnActivated(EventArgs e)
        {
            if (m_currentPage != null)
                m_currentPage.Resume();

            Invalidate();
            timer1.Enabled = m_currentPage.Name != "Home";

            base.OnActivated(e);
        }

        protected override void OnDeactivate(EventArgs e)
        {
            timer1.Enabled = false;
            if (m_currentPage != null)
                m_currentPage.Suspend();

            base.OnDeactivate(e);
        }

        private void ResetTimeoutTimer()
        {
            if (timer1.Enabled)
            {
                timer1.Enabled = false;
                timer1.Enabled = true;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            GotoPage("Home");
        }
    }
}